package com.lemlin.network

import androidx.annotation.NonNull
import com.google.gson.JsonParseException
import retrofit2.HttpException
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import java.util.concurrent.TimeoutException
import javax.net.ssl.SSLException

object HttpServiceException {

    /**
     * 4xx（请求错误）
     * 这些状态代码表示请求可能出错，妨碍了服务器的处理。
     */
    const val HTTP_400 = 400 //400 （错误请求） 服务器不理解请求的语法。

    const val HTTP_401 = 401 //401 （未授权） 请求要求身份验证。 对于需要登录的网页，服务器可能返回此响应。

    const val HTTP_403 = 403 //403 （禁止） 服务器拒绝请求。

    const val HTTP_404 = 404 //404 （未找到） 服务器找不到请求的网页。

    const val HTTP_405 = 405 //405 （方法禁用） 禁用请求中指定的方法。

    const val HTTP_406 = 406 //406 （不接受） 无法使用请求的内容特性响应请求的网页。

    const val HTTP_407 = 407 //407 （需要代理授权） 此状态代码与 401（未授权）类似，但指定请求者应当授权使用代理。

    const val HTTP_408 = 408 //408 （请求超时） 服务器等候请求时发生超时。

    const val HTTP_409 = 409 //409 （冲突） 服务器在完成请求时发生冲突。服务器必须在响应中包含有关冲突的信息。

    const val HTTP_410 = 410 //410 （已删除） 如果请求的资源已永久删除，服务器就会返回此响应。

    const val HTTP_411 = 411 //411 （需要有效长度） 服务器不接受不含有效内容长度标头字段的请求。

    const val HTTP_412 = 412 //412 （未满足前提条件） 服务器未满足请求者在请求中设置的其中一个前提条件。

    const val HTTP_413 = 413 //413 （请求实体过大） 服务器无法处理请求，因为请求实体过大，超出服务器的处理能力。

    const val HTTP_414 = 414 //414 （请求的 URI 过长） 请求的 URI（通常为网址）过长，服务器无法处理。

    const val HTTP_415 = 415 //415 （不支持的媒体类型） 请求的格式不受请求页面的支持。

    const val HTTP_416 = 416 //416 （请求范围不符合要求） 如果页面无法提供请求的范围，则服务器会返回此状态代码。

    const val HTTP_417 = 417 //417 （未满足期望值） 服务器未满足"期望"请求标头字段的要求。


    /**
     * 5xx（服务器错误）
     * 这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误，而不是请求出错。
     */
    const val HTTP_500 = 500 //500 （服务器内部错误） 服务器遇到错误，无法完成请求。

    const val HTTP_501 = 501 //501 （尚未实施） 服务器不具备完成请求的功能。例如，服务器无法识别请求方法时可能会返回此代码。

    const val HTTP_502 = 502 //502 （错误网关） 服务器作为网关或代理，从上游服务器收到无效响应。

    const val HTTP_503 = 503 //503 （服务不可用） 服务器目前无法使用（由于超载或停机维护）。通常，这只是暂时状态。

    const val HTTP_504 = 504 //504 （网关超时） 服务器作为网关或代理，但是没有及时从上游服务器收到请求。

    const val HTTP_505 = 505 //505 （HTTP 版本不受支持） 服务器不支持请求中所用的 HTTP 协议版本。


    fun handleThrowable(@NonNull throwable: Throwable): ResponseException {
        return when (throwable) {
            is ConnectException -> ResponseException(
                ResponseException.ERROR.CONNECT.code, "连接错误"
            )
            is SSLException -> ResponseException(
                ResponseException.ERROR.SSL.code, "证书认证错误"
            )
            is TimeoutException, is SocketTimeoutException -> ResponseException(
                ResponseException.ERROR.TIMEOUT.code, "连接超时"
            )
            is UnknownHostException -> ResponseException(
                ResponseException.ERROR.HOST.code, "主机域名未知"
            )
            is JsonParseException -> ResponseException(
                ResponseException.ERROR.PARSE.code, "数据错误，解析失败"
            )
            is HttpException -> {
                ResponseException(
                    throwable.code(), "网络错误：${when (throwable.code()) {
                        HTTP_400 -> "错误请求"
                        HTTP_401 -> "未授权"
                        HTTP_403 -> "禁止"
                        HTTP_404 -> "未找到"
                        HTTP_405 -> "方法禁用"
                        HTTP_406 -> "不接受"
                        HTTP_407 -> "需要代理授权"
                        HTTP_408 -> "请求超时"
                        HTTP_409 -> "冲突"
                        HTTP_410 -> "已删除"
                        HTTP_411 -> "需要有效长度"
                        HTTP_412 -> "未满足前提条件"
                        HTTP_413 -> "请求实体过大"
                        HTTP_414 -> "请求的URI过长"
                        HTTP_415 -> "不支持的媒体类型"
                        HTTP_416 -> "请求范围不符合要求"
                        HTTP_417 -> "未满足期望值"
                        HTTP_500 -> "服务器内部错误"
                        HTTP_501 -> "服务器不具备完成请求的功能"
                        HTTP_502 -> "错误网关"
                        HTTP_503 -> "服务不可用"
                        HTTP_504 -> "网关超时"
                        HTTP_505 -> "HTTP版本不受支持"
                        else -> "Http未知错误:${throwable.code()},${throwable.message}".trimIndent()
                    }}"
                )
            }
            else -> ResponseException(
                ResponseException.ERROR.UNKNOWN.code,
                throwable.message
            )
        }
    }

    class ResponseException(val code: Int, message: String?) : Exception(message) {
        enum class ERROR(val code: Int) {
            CONNECT(0x0000FF),
            SSL(0x00FF00),
            HOST(0x00FFFF),
            TIMEOUT(0xFF0000),
            UNKNOWN(0xFF00FF),
            PARSE(0xFFFF00)
        }
    }
}